﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace DienLib.SummitLib
{
    /// <summary>
    /// Wrapper for Infragistics.Win.UIElement in Summit Main Form
    /// </summary>
    public class UIElement
    {
        private object _refobj;
        private Control _reftree;

        public UIElement(object refUIElement, Control refUltraTreeView)
        {
            _refobj = refUIElement;
            _reftree = refUltraTreeView;
        }

        /// <summary>
        /// Return the Original Wrapped Object for this Wrapper
        /// </summary>
        public object Wrappee
        {
            get
            {
                return _refobj;
            }
        }

        /// <summary>
        /// return Last UIElement that this object entered in as Infragistic.Win.UIElement
        /// </summary>
        public UIElement LastElementEntered
        {
            get
            {
                if (_reftree.InvokeRequired) return new UIElement(_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.GetProperty<object>(_refobj, "LastElementEntered"); }), _reftree);
                else return new UIElement(DienLib.Reflector.GetProperty<object>(_refobj, "LastElementEntered"), _reftree);
            }
        }

        public Control Control
        {
            get
            {
                if (_reftree.InvokeRequired) return (Control)_reftree.Invoke((Func<Control>)delegate { return DienLib.Reflector.GetProperty<Control>(_refobj, "Control"); });
                else return DienLib.Reflector.GetProperty<Control>(_refobj, "Control");
            }
        }

        public Rectangle Rect
        {
            get
            {
                if (_reftree.InvokeRequired) return (Rectangle)_reftree.Invoke((Func<Rectangle>)delegate { return DienLib.Reflector.GetProperty<Rectangle>(_refobj, "Rect"); });
                else return DienLib.Reflector.GetProperty<Rectangle>(_refobj, "Rect");
            }
        }

        public UIElement GetAncestor(Type type)
        {
            if (_reftree.InvokeRequired) return new UIElement(_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.DoMethod<object>(_refobj, "GetAncestor", new object[] { type }); }), _reftree);
            else return new UIElement(DienLib.Reflector.DoMethod<object>(_refobj, "GetAncestor", new object[] { type }), _reftree); // object above is Infragistics.Win.UIElement
        }

        public UIElement GetDescendant(Type type)
        {   // GetDescendant have 3 overload (Type) | (Type, object) | (Type, object[])
            if (_reftree.InvokeRequired) return new UIElement(_reftree.Invoke((Func<object>)delegate { return DienLib.Reflector.DoOverloadMethod<object>(_refobj, "GetDescendant", new Type[] { typeof(Type) }, new object[] { type }); }), _reftree);
            else return new UIElement(DienLib.Reflector.DoOverloadMethod<object>(_refobj, "GetDescendant", new Type[] { typeof(Type) }, new object[] { type }), _reftree); // object above is Infragistics.Win.UIElement
        }

        #region DISPOSE METHOD
        // Dispose() calls Dispose(true)
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // NOTE: Leave out the finalizer altogether if this class doesn't 
        // own unmanaged resources itself, but leave the other methods
        // exactly as they are. 
        ~UIElement()
        {
            // Finalizer calls Dispose(false)
            Dispose(false);
        }

        // The bulk of the clean-up code is implemented in Dispose(bool)
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                // free managed resources, (detach event ?)
                if (this._refobj != null) this._refobj = null; // Khong keu this._refobj.Dispose vi Reference toi object do. Ngoai ra do pass reference nen this._refobj = null khong anh huong gi toi object goc
                if (this._reftree != null) this._reftree = null;
            }

            /* free native resources if there are any.
            if (nativeResource != IntPtr.Zero) 
            {
                Marshal.FreeHGlobal(nativeResource);
                nativeResource = IntPtr.Zero;
            }*/
        }
        #endregion
    }
}